package com.wskj.pay.impl;


import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.wskj.common.core.domain.AjaxResult;
import com.wskj.config.properties.AliPayConstants;
import com.wskj.pay.IAliService;
import com.wskj.system.domain.SysCommon;
import com.wskj.system.service.ISysCommonService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * @author GUN
 * @date 2023/5/23
 */
@Slf4j
@AllArgsConstructor
@Service
public class AliServiceImpl implements IAliService {

    private final ISysCommonService iSysCommonService;

    public AjaxResult payApp(Double moneys,String outTradeNo,String attach){
        SysCommon one = iSysCommonService.getById(1000048L);
        String url = one.getCommonValue() + "/stage-api/api/ali/pay/notify";
        String result = "";
        SysCommon payWay = iSysCommonService.getById(1000015L);
        // 后台服务名称
        SysCommon body = iSysCommonService.getById(1000054L);
        try{
            if ("1".equals(payWay.getCommonValue())) {
                //构造client
                CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
                //设置网关地址
                certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
                //设置应用Id
                certAlipayRequest.setAppId(iSysCommonService.getById(1000009L).getCommonValue());
                //设置应用私钥
                certAlipayRequest.setPrivateKey(iSysCommonService.getById(1000010L).getCommonValue());
                //设置请求格式，固定值json
                certAlipayRequest.setFormat("json");
                //设置字符集
                certAlipayRequest.setCharset(AliPayConstants.CHARSET);
                //设置签名类型
                certAlipayRequest.setSignType(AliPayConstants.SIGNTYPE);
                SysCommon urls = iSysCommonService.getById(1000016L);
                certAlipayRequest.setCertPath(urls.getCommonValue() + "/appCertPublicKey_"+iSysCommonService.getById(1000009L).getCommonValue()+".crt"); //应用公钥证书路径（app_cert_path 文件绝对路径）
                certAlipayRequest.setAlipayPublicCertPath(urls.getCommonValue() + "/alipayCertPublicKey_RSA2.crt"); //支付宝公钥证书文件路径（alipay_cert_path 文件绝对路径）
                certAlipayRequest.setRootCertPath(urls.getCommonValue() + "/alipayRootCert.crt");  //支付宝CA根证书文件路径（alipay_root_cert_path 文件绝对路径）
                //构造client
                AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);

                //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
                AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
                //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
                AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
                model.setBody(body.getCommonValue());
                model.setSubject(body.getCommonValue());
                model.setOutTradeNo(outTradeNo);
                model.setTimeoutExpress("30m");
                model.setTotalAmount(String.valueOf(moneys));
                model.setProductCode("QUICK_MSECURITY_PAY");
                model.setPassbackParams(attach);
                request.setBizModel(model);
                request.setNotifyUrl(url);
                //这里和普通的接口调用不同，使用的是sdkExecute
                AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
                if (response.isSuccess()) {
                    result = response.getBody();
                } else {
                    return AjaxResult.error("获取订单失败！");
                }
                return AjaxResult.success("支付宝预支付",result);
            } else {
                //实例化客户端
                AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", iSysCommonService.getById(1000009L).getCommonValue(), iSysCommonService.getById(1000009L).getCommonValue(), "json", AliPayConstants.CHARSET, iSysCommonService.getById(1000012L).getCommonValue(), "RSA2");
                //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
                AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
                //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
                AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
                model.setBody(body.getCommonValue());
                model.setSubject(body.getCommonValue());
                model.setOutTradeNo(outTradeNo);
                model.setTimeoutExpress("30m");
                model.setTotalAmount(String.valueOf(moneys));
                model.setProductCode("QUICK_MSECURITY_PAY");
                model.setPassbackParams(attach);
                request.setBizModel(model);
                request.setNotifyUrl(url);
                AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
                if (response.isSuccess()) {
                    result = response.getBody();
                } else {
                    return AjaxResult.error("获取订单失败！");
                }
                return AjaxResult.success("支付宝预支付",result);
            }
        }catch(Exception e){
            e.printStackTrace();
            log.error("支付宝预支付异常:"+e.getMessage());
        }
        return AjaxResult.error("获取订单失败");


    }


    public AjaxResult payH5(Double moneys,String outTradeNo,String attach){
        // 支付宝方式 1 证书 2秘钥
        SysCommon payWay = iSysCommonService.getById(1000015L);
        SysCommon one = iSysCommonService.getById(1000048L);
        String url = one.getCommonValue() + "/stage-api/api/ali/pay/notify";
        // 后台服务名称
        SysCommon body = iSysCommonService.getById(1000054L);
        String result = "";
        try{
            if ("1".equals(payWay.getCommonValue())) {
                //构造client
                CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
                //设置网关地址
                certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
                //设置应用Id
                certAlipayRequest.setAppId(iSysCommonService.getById(1000009L).getCommonValue());
                //设置应用私钥
                certAlipayRequest.setPrivateKey(iSysCommonService.getById(1000010L).getCommonValue());
                //设置请求格式，固定值json
                certAlipayRequest.setFormat("json");
                //设置字符集
                certAlipayRequest.setCharset(AliPayConstants.CHARSET);
                //设置签名类型
                certAlipayRequest.setSignType(AliPayConstants.SIGNTYPE);
                SysCommon urls = iSysCommonService.getById(1000016L);
                certAlipayRequest.setCertPath(urls.getCommonValue() + "/appCertPublicKey_"+iSysCommonService.getById(1000009L).getCommonValue()+".crt"); //应用公钥证书路径（app_cert_path 文件绝对路径）
                certAlipayRequest.setAlipayPublicCertPath(urls.getCommonValue() + "/alipayCertPublicKey_RSA2.crt"); //支付宝公钥证书文件路径（alipay_cert_path 文件绝对路径）
                certAlipayRequest.setRootCertPath(urls.getCommonValue() + "/alipayRootCert.crt");  //支付宝CA根证书文件路径（alipay_root_cert_path 文件绝对路径）
                //构造client
                AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
                AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
                JSONObject order = new JSONObject();
                order.put("out_trade_no", outTradeNo); //订单号
                order.put("subject", body.getCommonValue()); //商品标题
                order.put("product_code", "QUICK_WAP_WAY");
                order.put("body", body.getCommonValue());//商品名称
                order.put("total_amount", moneys); //金额
                order.put("passback_params",attach);
                alipayRequest.setBizContent(order.toString());
                alipayRequest.setNotifyUrl(url); //在公共参数中设置回跳和通知地址
                alipayRequest.setReturnUrl(one.getCommonValue()); //线上通知页面地址
                AlipayTradeWapPayResponse response = alipayClient.pageExecute(alipayRequest);
                if (response.isSuccess()) {
                    result = response.getBody();
                } else {
                    return AjaxResult.error("获取订单失败！");
                }
                return AjaxResult.success("支付宝预支付",result);
            } else {
                AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", iSysCommonService.getById(1000009L).getCommonValue(),iSysCommonService.getById(1000010L).getCommonValue(), "json", AliPayConstants.CHARSET, iSysCommonService.getById(1000012L).getCommonValue(), "RSA2");
                AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
                JSONObject order = new JSONObject();
                order.put("out_trade_no", outTradeNo); //订单号
                order.put("subject", body.getCommonValue()); //商品标题
                order.put("product_code", "QUICK_WAP_WAY");
                order.put("body", body.getCommonValue());//商品名称
                order.put("total_amount", moneys); //金额\
                order.put("passback_params",attach);
                alipayRequest.setBizContent(order.toString());
                //在公共参数中设置回跳和通知地址
                alipayRequest.setNotifyUrl(url);
                //通知页面地址
                alipayRequest.setReturnUrl(one.getCommonValue());
                AlipayTradeWapPayResponse response = alipayClient.pageExecute(alipayRequest);
                if (response.isSuccess()) {
                    result = response.getBody();
                } else {
                    return AjaxResult.error("获取订单失败！");
                }
                return AjaxResult.success("支付宝预支付",result);
            }
        }catch(Exception e){
            e.printStackTrace();
            log.error("支付宝预支付异常:"+e.getMessage());
        }
        return AjaxResult.error("获取订单失败");
    }

    @Override
    public AjaxResult pay(Double moneys, Integer classify, Long userId, String outTradeNo, String attach) {
        if(classify==1){
            return payApp(moneys,outTradeNo,attach);
        }
        return payH5(moneys,outTradeNo,attach);
    }
    @Override
    public String payBack(Map<String,String> params) {
        try {
            log.info("支付宝回调成功！！！");
            SysCommon dbSysCommon = iSysCommonService.getById(1000015L);
            boolean flag = false;
            if("1".equals(dbSysCommon.getCommonValue())){
                // 证书模式
                SysCommon urls = iSysCommonService.getById(1000016L);
                // 应用公钥证书路径
                String aliPayCertPath = urls.getCommonValue() + "/alipayCertPublicKey_RSA2.crt";
                flag = AlipaySignature.rsaCertCheckV1(params, aliPayCertPath, AliPayConstants.CHARSET, AliPayConstants.SIGNTYPE);
            }else{
                // 秘钥模式
                flag = AlipaySignature.rsaCheckV1(params, iSysCommonService.getById(1000012L).getCommonValue(), AliPayConstants.CHARSET, AliPayConstants.SIGNTYPE);
            }
            log.info(flag + "回调验证信息");
            if (flag) {
                String tradeStatus = params.get("trade_status");
                if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                    // 支付宝返回的订单编号
                    String outTradeNo = params.get("out_trade_no");
                    log.error(outTradeNo);
                    // 支付宝支付单号
                    String inTradeNo = params.get("trade_no");
                    // 业务类型
                    String attach = params.get("passback_params");
                   /* if("1".equals(attach)){
                        iTbOrderService.notifyShopOrder(outTradeNo,inTradeNo,2);
                    }else if("2".equals(attach)){
                        iTbOrderService.notifyInviteOrder(outTradeNo,inTradeNo,2);
                    }else if("3".equals(attach)){
                        iTbBusinessService.notifyRecharge(outTradeNo,inTradeNo,2);
                    }else if("4".equals(attach)){
                        iTbBusinessService.notifyBuyVip(outTradeNo,inTradeNo,2);
                    }else if("5".equals(attach)){
                        iTbActivityService.notifyActivityEnroll(outTradeNo,inTradeNo,2);
                    }*/
                }
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            log.info("回调验证失败！！！");
        }
        return "";
    }

    public String getGeneralOrder() {
        Date date = new Date();
        String newString = String.format("%0" + 4 + "d", (int) ((Math.random() * 9 + 1) * 1000));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String format = sdf.format(date);
        return format + newString;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean refund(String outTradeNo,String inTradeNo, Double moneys) {
        SysCommon dbSysCommon = iSysCommonService.getById(1000015L);
        AlipayClient alipayClient = null;
        try{
            if("1".equals(dbSysCommon.getCommonValue())){
                // 证书模式
                //构造client
                CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
                //设置网关地址
                certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
                //设置应用Id
                certAlipayRequest.setAppId(iSysCommonService.getById(1000009L).getCommonValue());
                //设置应用私钥
                certAlipayRequest.setPrivateKey(iSysCommonService.getById(1000010L).getCommonValue());
                //设置请求格式，固定值json
                certAlipayRequest.setFormat("json");
                //设置字符集
                certAlipayRequest.setCharset(AliPayConstants.CHARSET);
                //设置签名类型
                certAlipayRequest.setSignType(AliPayConstants.SIGNTYPE);
                SysCommon urls = iSysCommonService.getById(1000016L);
                certAlipayRequest.setCertPath(urls.getCommonValue() + "/appCertPublicKey_"+iSysCommonService.getById(1000009L).getCommonValue()+".crt"); //应用公钥证书路径（app_cert_path 文件绝对路径）
                certAlipayRequest.setAlipayPublicCertPath(urls.getCommonValue() + "/alipayCertPublicKey_RSA2.crt"); //支付宝公钥证书文件路径（alipay_cert_path 文件绝对路径）
                certAlipayRequest.setRootCertPath(urls.getCommonValue() + "/alipayRootCert.crt");  //支付宝CA根证书文件路径（alipay_root_cert_path 文件绝对路径）
                //构造client
                 alipayClient = new DefaultAlipayClient(certAlipayRequest);
            }else{
                // 密钥模式
                alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", iSysCommonService.getById(63).getCommonValue(), iSysCommonService.getById(65).getCommonValue(), "json", AliPayConstants.CHARSET, iSysCommonService.getById(64).getCommonValue(), "RSA2");
            }
            AlipayTradeRefundRequest alipay_request = new AlipayTradeRefundRequest();
            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            model.setOutTradeNo(outTradeNo);//订单编号
            model.setTradeNo(inTradeNo);//支付宝订单交易号
            model.setRefundAmount(moneys.toString());//退款金额 不得大于订单金额
            model.setRefundReason("服务退款");//退款说明
            model.setOutRequestNo(IdWorker.getIdStr());//标识一次退款请求，同一笔交易多次退款需要保证唯一，如需部分退款，则此参数必传。
            alipay_request.setBizModel(model);
            AlipayTradeRefundResponse alipay_response = alipayClient.certificateExecute(alipay_request);
            String alipayRefundStr = alipay_response.getBody();
            log.info(alipayRefundStr);
            return Boolean.TRUE;
        }catch(Exception e){
            e.printStackTrace();
            log.error("支付宝退款异常:"+e.getMessage());
        }
        return Boolean.FALSE;
    }
}